package com.lmb.todo.utils;

import com.lmb.todo.pojo.User;
import io.jsonwebtoken.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author Lenovo
 */
public class JwtUtil {

    /**
     * token 过期时间
     */
    private static final long TIME = 1000 * 60 * 60 * 24;

    /**
     * Jwt 签名
     */
    private static final String SIGNATURE = Constant.TODOAUTH;

    /**
     * 创建随机 token
     * @param user User
     * @return String
     */
    public static String createToken(User user) {
        JwtBuilder jwtBuilder = Jwts.builder();
        return jwtBuilder
                // header
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                //payload
                .claim("username", user.getUsername())
                .claim("password", user.getPassword())
                .claim("userId", user.getId())
                .setSubject( SIGNATURE)
                .setExpiration(DateUtil.afterHowLong(TIME))
                .setId(UUID.randomUUID().toString())
                // signature
                .signWith(SignatureAlgorithm.HS256, SIGNATURE)
                .compact();
    }

    /**
     * 获取用于解析 token 的 Claims 对象
     * @param token String
     * @return Claims
     */
    public static Claims parse(String token) {
        JwtParser jwtParser = Jwts.parser();
        return jwtParser.setSigningKey(SIGNATURE).parseClaimsJws(token).getBody();
    }

    /**
     * 检查 token 是否过期
     * @param token String
     * @return boolean
     */
    public static boolean checkToken(String token, HttpServletRequest req) {
        HttpSession session = req.getSession();
        String tokenInSession = (String) session.getAttribute("token");

        if (tokenInSession == null || !tokenInSession.equals(token)) {
            return false;
        }

        try {
            parse(token);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * 获取 token 的加密信息
     * @param token String
     * @param key String
     * @return Object
     */
    public static Object get(String token, String key) {
        Claims claims = parse(token);
        Object value;

        switch (key) {
            case "expiration":
                value = claims.getExpiration();
                break;
            case "id":
                value = claims.getId();
                break;
            case "subject":
                value = claims.getSubject();
                break;
            default:
                value = claims.get(key);
        }

        return value;
    }

    /**
     * 以 Map 的形式返回 token 中的 payload 信息
     * @param token String
     * @return Map<String, Object>
     */
    public static Map<String, Object> getPayload(String token) {
        Map<String ,Object> map = new HashMap<>(3);
        map.put("username", get(token, "username"));
        map.put("password", get(token, "password"));
        map.put("userId", get(token, "userId"));
        return map;
    }

}
